/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *
 *
 *
 *
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package java.util.concurrent;

import java.util.Collection;
import java.util.Queue;

/**
 * <p> 1、BlockingQueue不接受null元素。实现在尝试添加、放置或提供null时抛出NullPointerException。null用作指示轮询操作失败的哨值。
 * <p> 2、BlockingQueue队列容量{@code Integer.MAX_VALUE}
 * <p> 3、BlockingQueue实现主要用于生产者-消费者队列
 * <p> 4、BlockingQueue实现是线程安全的,可以安全地与多个生产者和多个消费者一起使用。
 *
 *
 * 实现类
 * {@link ArrayBlockingQueue}
 * {@link LinkedBlockingQueue}
 * {@link SynchronousQueue}

 * {@link  DelayQueue}
 * {@link LinkedBlockingDeque}
 * {@link LinkedTransferQueue}
 * {@link PriorityBlockingQueue}
 */
public interface BlockingQueue<E> extends Queue<E> {


    // 放入数据

    /**
     * 如果可以在不违反容量限制的情况下立即将指定元素插入此队列，则在成功时返回true
     * <p>如果当前没有可用空间则IllegalStateException
     * <p>当使用容量受限的队列时，通常最好使用offer
     */
    boolean add(E e);
    /**
     * 如果可能的话，将e加到BlockingQueue里
     * 如果BlockingQueue可以容纳，则返回true，否则返回false（本方法不阻塞当前执行方法的线程）。
     */
    boolean offer(E e);
    /**
     * 可以设定等待的时间，如果在指定的时间内，还不能往队列中加入e，则返回失败
     */
    boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
    /**
     * 把e加到BlockingQueue里
     * 如果BlockQueue没有空间，则调用此方法的线程被阻塞，直到BlockingQueue里面有空间再继续。
     */
    void put(E e) throws InterruptedException;



    // 获取数据

    /**
     * 从BlockingQueue取出一个队首的对象
     * <p>如果在指定时间内，队列一旦有数据可取，则立即返回队列中的数据
     * <p>否则时间超时还没有数据可取，返回失败
     */
    E poll(long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * 取走BlockingQueue里排在首位的对象
     * <p>若BlockingQueue为空，阻塞进入等待状态直到BlockingQueue有新的数据被加入
     */
    E take() throws InterruptedException;

    /**
     * 一次性从BlockingQueue获取所有可用的数据对象,还可以指定获取数据的个数
     */
    int drainTo(Collection<? super E> c);

    /**
     * 通过该方法，可以提升获取数据效率；不需要多次分批加锁或释放锁
     */
    int drainTo(Collection<? super E> c, int maxElements);



    // 删除数据
    
    /**
     * 从此队列中移除指定元素的单个实例（如果存在）。则返回true
     */
    boolean remove(Object o);

    /**
     * 剩余容量,不能总是通过检查remainingCapacity来判断插入元素的尝试是否会成功，因为可能是另一个线程即将插入或删除元素。
     */
    int remainingCapacity();

    /**
     * 如果此队列包含指定的元素，则返回true。更正式地说，当且仅当该队列至少包含一个元素e，使得o.equals（e）时，返回true。
     */
     boolean contains(Object o);


}
